<?php
// 百度OCR处理文件

require_once 'config.php';
// 引入百度OCR SDK
require_once 'baiduAipSDK/AipOcr.php';

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

// 获取访问令牌
function getBaiduAccessToken($apiKey, $secretKey) {
    $url = 'https://aip.baidubce.com/oauth/2.0/token';
    
    $postData = http_build_query([
        'grant_type' => 'client_credentials',
        'client_id' => $apiKey,
        'client_secret' => $secretKey
    ]);
    
    // 使用cURL而不是file_get_contents以获得更好的错误处理
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/x-www-form-urlencoded'
    ]);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    
    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);
    
    if ($result === false) {
        throw new Exception('无法获取访问令牌: 网络错误 - ' . $error);
    }
    
    if ($httpCode !== 200) {
        throw new Exception('无法获取访问令牌: HTTP错误 ' . $httpCode);
    }
    
    $data = json_decode($result, true);
    
    if (isset($data['error'])) {
        throw new Exception('获取访问令牌失败: ' . ($data['error_description'] ?? $data['error']));
    }
    
    return $data;
}

// 调用百度OCR API（使用官方SDK）
function callBaiduOcrApiWithSDK($imageData, $apiKey, $secretKey) {
    try {
        // 初始化OCR客户端 (appId, apiKey, secretKey)
        $client = new AipOcr('', $apiKey, $secretKey);
        
        // 设置超时时间
        $client->setConnectionTimeoutInMillis(2000);
        $client->setSocketTimeoutInMillis(60000);
        
        // 调用数字识别接口
        $options = [
            'recognize_granularity' => 'small',
            'detect_direction' => 'false',
            'probability' => 'true',
            'accuracy' => 'high',
            'vertexes_location' => 'true',
            'classify_dimension' => 'lottery'
        ];
        
        // 检查图像数据是否有效
        if (empty($imageData)) {
            throw new Exception('图像数据为空');
        }
        
        // 调用OCR接口，直接传入base64数据
        $result = $client->numbers($imageData, $options);
        
        // 添加调试信息
        error_log('百度OCR SDK识别结果: ' . print_r($result, true));
        
        return $result;
    } catch (Exception $e) {
        error_log('百度OCR SDK调用异常: ' . $e->getMessage());
        throw new Exception('调用百度OCR SDK失败: ' . $e->getMessage());
    }
}

/**
 * 从OCR结果中提取所有单个数字
 */
function extractAllSingleDigits($wordsResult) {
    $singleDigits = [];
    
    foreach ($wordsResult as $word) {
        $text = $word['words'];
        
        // 如果是单个数字，直接添加
        if (preg_match('/^[0-9]$/', $text)) {
            $singleDigits[] = $word;
        } 
        // 如果包含多个数字，尝试拆分
        else if (preg_match('/^[0-9]+$/', $text) && strlen($text) > 1) {
            // 获取原始位置信息
            $location = $word['location'];
            $left = $location['left'];
            $top = $location['top'];
            $width = $location['width'];
            $height = $location['height'];
            
            // 计算每个数字的宽度
            $digitWidth = $width / strlen($text);
            
            // 为每个数字创建单独的条目
            for ($i = 0; $i < strlen($text); $i++) {
                $digit = $text[$i];
                $digitLocation = [
                    'left' => $left + $i * $digitWidth,
                    'top' => $top,
                    'width' => $digitWidth,
                    'height' => $height
                ];
                
                $singleDigits[] = [
                    'words' => $digit,
                    'location' => $digitLocation
                ];
            }
        }
        // 处理包含连字符的情况（如"7-6"）
        else if (preg_match('/^[0-9]-[0-9]$/', $text)) {
            // 获取原始位置信息
            $location = $word['location'];
            $left = $location['left'];
            $top = $location['top'];
            $width = $location['width'];
            $height = $location['height'];
            
            // 分离数字
            $parts = explode('-', $text);
            
            // 计算每个数字的宽度
            $digitWidth = $width / 3; // 两个数字和一个连字符
            
            // 为每个数字创建单独的条目
            for ($i = 0; $i < count($parts); $i++) {
                $digit = $parts[$i];
                $digitLocation = [
                    'left' => $left + $i * $digitWidth * 2, // 跳过连字符位置
                    'top' => $top,
                    'width' => $digitWidth,
                    'height' => $height
                ];
                
                $singleDigits[] = [
                    'words' => $digit,
                    'location' => $digitLocation
                ];
            }
        }
    }
    
    return $singleDigits;
}

/**
 * 将识别到的数字按位置排列成9x9数独网格
 */
function arrangeDigitsToSudokuGrid($digits) {
    // 初始化9x9网格
    $grid = array_fill(0, 9, array_fill(0, 9, 0));
    
    if (empty($digits)) {
        return $grid;
    }
    
    // 确定网格边界
    $minX = PHP_INT_MAX;
    $maxX = 0;
    $minY = PHP_INT_MAX;
    $maxY = 0;
    
    foreach ($digits as $digit) {
        $x = $digit['location']['left'];
        $y = $digit['location']['top'];
        $minX = min($minX, $x);
        $maxX = max($maxX, $x);
        $minY = min($minY, $y);
        $maxY = max($maxY, $y);
    }
    
    // 添加边界缓冲区
    $bufferX = ($maxX - $minX) * 0.05;
    $bufferY = ($maxY - $minY) * 0.05;
    $minX -= $bufferX;
    $maxX += $bufferX;
    $minY -= $bufferY;
    $maxY += $bufferY;
    
    // 计算每个单元格的宽度和高度
    $cellWidth = ($maxX - $minX) / 9;
    $cellHeight = ($maxY - $minY) / 9;
    
    // 将数字放入对应网格位置
    foreach ($digits as $digit) {
        $x = $digit['location']['left'];
        $y = $digit['location']['top'];
        
        // 计算行列索引
        $col = floor(($x - $minX) / $cellWidth);
        $row = floor(($y - $minY) / $cellHeight);
        
        // 确保索引在有效范围内
        $col = max(0, min(8, $col));
        $row = max(0, min(8, $row));
        
        // 放入网格（如果该位置还没有数字）
        if ($grid[$row][$col] == 0) {
            $grid[$row][$col] = (int)$digit['words'];
        }
    }
    
    return $grid;
}

// 处理请求
try {
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $input = json_decode(file_get_contents('php://input'), true);
        // 记录输入参数用于调试
        error_log('百度OCR请求参数: ' . print_r($input, true));
        
        if (isset($input['action'])) {
            switch ($input['action']) {
                case 'get_token':
                    // 从配置中获取API密钥
                    $apiKey = $config['baiduOcr']['apiKey'] ?? '';
                    $secretKey = $config['baiduOcr']['secretKey'] ?? '';
                    
                    if (empty($apiKey) || empty($secretKey)) {
                        throw new Exception('API密钥未配置');
                    }
                    
                    $tokenData = getBaiduAccessToken($apiKey, $secretKey);
                    // 记录令牌信息用于调试（隐藏敏感信息）
                    $logTokenData = $tokenData;
                    if (isset($logTokenData['access_token'])) {
                        $logTokenData['access_token'] = '***隐藏***';
                    }
                    error_log('百度OCR令牌数据: ' . print_r($logTokenData, true));
                    echo json_encode(['success' => true, 'data' => $tokenData]);
                    break;
                    
                case 'recognize':
                    if (!isset($input['imageData'])) {
                        throw new Exception('缺少图像数据');
                    }
                    
                    // 从配置中获取API密钥
                    $apiKey = $config['baiduOcr']['apiKey'] ?? '';
                    $secretKey = $config['baiduOcr']['secretKey'] ?? '';
                    
                    if (empty($apiKey) || empty($secretKey)) {
                        throw new Exception('API密钥未配置');
                    }
                    
                    // 添加额外的调试信息
                    error_log('百度OCR图像数据长度: ' . strlen($input['imageData']));
                    
                    // 使用官方SDK进行OCR识别，直接传入base64数据
                    $ocrResult = callBaiduOcrApiWithSDK($input['imageData'], $apiKey, $secretKey);
                    
                    // 提取所有单个数字（包括从多数字文本块中拆分出来的）
                    if (isset($ocrResult['words_result']) && is_array($ocrResult['words_result'])) {
                        $allSingleDigits = extractAllSingleDigits($ocrResult['words_result']);
                        $ocrResult['single_digits'] = $allSingleDigits;
                        $ocrResult['sudoku_grid'] = arrangeDigitsToSudokuGrid($allSingleDigits);
                    }
                    
                    // 记录OCR识别结果用于调试
                    error_log('百度OCR SDK识别结果: ' . print_r($ocrResult, true));
                    echo json_encode(['success' => true, 'data' => $ocrResult]);
                    break;
                    
                default:
                    throw new Exception('未知操作');
            }
        } else {
            throw new Exception('缺少操作参数');
        }
    } else {
        throw new Exception('只支持POST请求');
    }
} catch (Exception $e) {
    // 记录错误日志
    error_log('百度OCR错误: ' . $e->getMessage());
    
    // 根据错误类型返回适当的状态码
    if (strpos($e->getMessage(), '无法获取访问令牌') !== false || 
        strpos($e->getMessage(), '无法调用百度OCR API') !== false) {
        http_response_code(500); // 服务器内部错误
    } else {
        http_response_code(400); // 客户端错误
    }
    
    echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
?>